<?php
/*
	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
	
	---------------------------------------------------------------------
	
    Name:		NZ Post Shipping Module Plus
	
	OpenCart:	Version 1.5.4.1
    
    Copyright:  2012 rebdog (Godfrey) godfrey@satelliteshop.co.nz
                2011-2012 Andy Carroll andy@goldfishinteractive.co.nz
 
    If you're going to use the code, give some credit.. it's simple

*/
class ModelShippingNZPost extends Model {
	function getQuote($address) {
		$this->load->language('shipping/nzpost');
		
		$method_data = array();
		$quote_data = array();       

		if ($this->config->get('nzpost_status')) {
      		$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "zone_to_geo_zone WHERE geo_zone_id = '" . (int)$this->config->get('nzpost_geo_zone_id') . "' AND country_id = '" . (int)$address['country_id'] . "' AND (zone_id = '" . (int)$address['zone_id'] . "' OR zone_id = '0')");
		
      		if (!$this->config->get('nzpost_geo_zone_id')) {
        		$status = TRUE;
      		} elseif ($query->num_rows) {
        		$status = TRUE;
      		} else {
        		$status = FALSE;
      		}
		} else {
			$status = FALSE;
		}

        if (!$status){
            return method_data();
        }
        
		if($this->config->get('nzpost_length_class_id') == 0 || $this->config->get('nzpost_weight_class_id') == 0)
		{
			$method_data = array(
				'code'       => 'nzpost',
				'title'      => $this->language->get('text_title'),
				'quote'      => $quote_data,
				'sort_order' => $this->config->get('nzpost_sort_order'),
				'error'      => $this->language->get('error_units')
			);
			return $method_data;
		}
		
		// Volume
		$volume = $this->getCubicVolume();
		
		if($volume == 0)
		{
			$method_data = array(
				'code'       => 'nzpost',
				'title'      => $this->language->get('text_title'),
				'quote'      => $quote_data,
				'sort_order' => $this->config->get('nzpost_sort_order'),
				'error'      => $this->language->get('error_volume')
			);
			return $method_data;
		}
        
		$packageLength = pow($volume, 1/3);
		$packageWidth = pow($volume, 1/3);
		$packageHeight = pow($volume, 1/3);
				
		// Weight
		$weight = $this->weight->convert($this->cart->getWeight(), $this->config->get('config_weight_class_id'), $this->config->get('nzpost_weight_class_id'));
		$weight = ($weight < 0.1 ? 0.1 : $weight);
		
		// NZ Domestic
		if ($status && $address['iso_code_2'] == 'NZ') {
			
			$url = 'http://api.nzpost.co.nz/ratefinder/rate.json';
			$url .= '?api_key=' . $this->config->get('nzpost_api_key');
			$url .= '&format=' . 'json';
			$url .= '&carrier=' . $this->config->get('nzpost_carrier');
			$url .= '&weight=' . $weight;
			$url .= '&length=' . $packageLength;
			$url .= '&thickness=' . $packageWidth;
			$url .= '&height=' . $packageHeight;
			$url .= '&postcode_src=' . $this->config->get('nzpost_source_postcode');
			$url .= '&postcode_dest=' . $address['postcode'];
            $url .= '&dest_wildcard=1';
			
			$ch = curl_init($url);
			curl_setopt($ch, CURLOPT_TIMEOUT, 60);  
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
			$response = curl_exec($ch);
			curl_close($ch);
			
			$result = json_decode($response);
			
			$error = '';
			$error_msg = '';
			
			if ($result->status == "success") {
                
                $invalid_postcode = FALSE;
                
                // Check if the destination postcode is valid
                if ($result->info->resolved_postcode_dest == '') {
                    // NZ Post does not recognise the Postcode
                    $invalid_postcode = TRUE;
                }
                                
                // Calculate the Price Inclusive of GST/Price Exclusive of GST ratio, so we can convert 
                // the GST inclusive price to a GST exclusive price, calculate here so only need to do it once
                $gst_ratio = $this->tax->calculate(1, $this->config->get('nzpost_tax_class_id'), $this->config->get('config_tax')); 
                
                // currently the API returns the same value for
                // "courier_large_delivery_type" and "post_large_delivery_type"
                // so just check "post_large_delivery_type"
                $service_distance = 'nzpost_service_' . $result->post_large_delivery_type;
                
                // if the postcode/address is rural then the last product will have 'PCBRURAL'
                // in the code so we can use it to check if the address is rural
                if (strpos(strtoupper(end($result->products)->code),'PCBRURAL') !== false ) {
                    $service_distance = $service_distance . '_r';
                }
                
                foreach ($result->products as $product) {
                
                    $code = str_replace(",","_",strtolower($product->code));
					
					if (in_array(strtoupper($code), $this->config->get($service_distance)) || 
                        !$this->config->get('nzpost_apply_filters')) {
                      
                        $quote_data[$code] = array(
                            'code'         => 'nzpost.' . $code,
                            'title'        => $product->description.' '.$product->speed_description,
                            'cost'         => $this->currency->convert($product->cost/$gst_ratio, $this->config->get('nzpost_currency_code'), $this->config->get('config_currency')),
                            'tax_class_id' => $this->config->get('nzpost_tax_class_id'),
                            'text'         => $this->currency->format($this->currency->convert($product->cost, $this->config->get('nzpost_currency_code'), $this->config->get('config_currency')))
                        );
                    }
                }
            } else {
                $error = $result->status;
                $error_msg = '';
            }
		
            if ($quote_data) {
            
                $title = $this->language->get('text_title');
                
                if ($this->config->get('nzpost_display_weight')) {	  
                    $title .= ' (' . $this->language->get('text_weight') . ' ' . $this->weight->format($weight, $this->config->get('nzpost_weight_class_id')) . ')';
                }
                
                // This code is horid but it does work
                if ($invalid_postcode) {
                    $title .= '</b></td></tr><tr><td colspan="3"><div class="error">' . $this->language->get('text_invalid_postcode') . '</div></td></tr><tr><td><b>';
                }
                
                $method_data = array(
                    'code'       => 'nzpost',
                    'title'      => $title,
                    'quote'      => $quote_data,
                    'sort_order' => $this->config->get('nzpost_sort_order'),
                    'error'      => $error_msg
                );
            }
        }
		else // International Postage
		{
			$destination_city = $address['city'];
			$destination_zone_code = $address['zone_code'];
			$destination_iso_code_2 = $address['iso_code_2'];
			$destination_postcode = $address['postcode'];
			
			$url = 'http://api.nzpost.co.nz/ratefinder/international.json';
			$url .= '?api_key=' . $this->config->get('nzpost_api_key');
			$url .= '&format=' . 'json';
			$url .= '&weight=' . $weight;
			$url .= '&length=' . $packageLength;
			$url .= '&thickness=' . $packageWidth;
			$url .= '&height=' . $packageHeight;
			$url .= '&country_code=' . $address['iso_code_2'];
			$url .= '&value=' . $this->cart->getTotal();
			
			$ch = curl_init($url);
			curl_setopt($ch, CURLOPT_TIMEOUT, 60);  
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
			$response = curl_exec($ch);
			curl_close($ch);
			
			$result = json_decode($response);
			
			$error = '';
			$error_msg = '';
			
			if ($result->status == "success") {
            
                if($this->config->get('nzpost_gst_paid_on_intl_postage')) {
                    $intl_price_name = "price_including_gst";
                } else {
                    $intl_price_name = "price";
                }
                
				foreach ($result->products as $product) {
					if((($this->config->get('nzpost_international_signature')=='') || $product->signature_required == '1') && 
					   (($this->config->get('nzpost_international_tracking')=='') || $product->has_tracking == '1')){
						$quote_data['nzpost_'.$product->service_code] = array(
							'code'         => 'nzpost.nzpost_'.$product->service_code,
							'title'        => $product->group.' - '.$product->min_delivery_target.'-'.$product->max_delivery_target.' days.',
							'cost'         => $this->currency->convert($product->$intl_price_name, $this->config->get('nzpost_currency_code'), $this->config->get('config_currency')),
							'tax_class_id' => 0,
							'text'         => $this->currency->format($this->currency->convert($product->$intl_price_name, $this->config->get('nzpost_currency_code'), $this->config->get('config_currency')))
						);
					}
				}
                
			} else {
				$error = $response->status;
				$error_msg = '';
			}
			
			$title = $this->language->get('text_title');
			
			if ($this->config->get('nzpost_display_weight')) {	  
				$title .= ' (' . $this->language->get('text_weight') . ' ' . $this->weight->format($weight, $this->config->get('nzpost_weight_class_id')) . ')';
			}
		
			$method_data = array(
				'code'       => 'nzpost',
				'title'      => $title,
				'quote'      => $quote_data,
				'sort_order' => $this->config->get('nzpost_sort_order'),
				'error'      => $error_msg
			);
		}
				
		return $method_data;
	}

	function getCubicVolume()
	{
		$totalVolume = 0;
		foreach ($this->cart->getProducts() as $key=>$attrs) {
			if ($attrs['shipping']) {
				$quantity = trim($attrs['quantity']);
				$length = trim($attrs['length']);
				$width = trim($attrs['width']);
				$height = trim($attrs['height']);
				if (is_numeric($length) && $length > 0 && is_numeric($width) && $width > 0 && is_numeric($height) && $height > 0) {
					
					$length = $this->length->convert($length, $attrs['length_class_id'], $this->config->get('nzpost_length_class_id'));
					$width = $this->length->convert($width, $attrs['length_class_id'], $this->config->get('nzpost_length_class_id'));
					$height = $this->length->convert($height, $attrs['length_class_id'], $this->config->get('nzpost_length_class_id'));
					
					$totalVolume = $totalVolume + ($quantity * ($length * ($width * $height)));
				}
				else
				{
					return 0;
				}
			}
		}
		return $totalVolume;
	}

}
?>